﻿using JinYuan.Models;
using System;
using System.Collections.Generic;
using System.Linq;

namespace JinYuan.Helper
{
    public static class PLCAlarmParseHelper
    {
        /// <summary>
        /// 三菱将报警地址值转成报警List
        /// </summary>
        /// <param name="plcAddrSuffix">PLC地址值，如100</param>
        /// <param name="byteData">PLC读取出来的值</param>
        /// <param name="plcAddrPrefix">PLC地址类型,默认值R</param>
        /// <returns></returns>
        public static List<AlarmStatus> MelsecByte2Status(int plcAddrSuffix, byte[] byteData, char plcAddrPrefix = 'R')
        {
            var listAlarmStatus = new List<AlarmStatus>();
            // byte[]转为二进制字符串表示
            string strResult = "";
            for (int i = 0; i < byteData.Length; i++)
            {
                string strTemp = System.Convert.ToString(byteData[i], 2);
                strTemp = strTemp.PadLeft(8, '0').StrReverse();
                strResult += strTemp;
            }

            for (int i = 0; i < strResult.Length; i++)
            {
                var plcByte = i % 16;
                //如果是16的倍数地址+1
                if (plcByte % 16 == 0 && i != 0)
                {
                    plcAddrSuffix++;
                }
                //将地址和状态添加到结果集
                listAlarmStatus.Add(new AlarmStatus()
                {
                    PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}",
                    Status = strResult[i] == '1'
                });
                //if (strResult[i] == '1')
                //    Console.WriteLine($"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}:{strResult[i]}");
            }

            return listAlarmStatus;
        }


        /// <summary>
        /// 欧姆龙NX系列Ethernet/IP通讯时将报警地址值转成报警List  {直接读取标签地址/无需高低位互换}
        /// </summary>
        /// <param name="plcAddrSuffix">PLC地址值，如100</param>
        /// <param name="byteData">PLC读取出来的值</param>
        /// <param name="plcAddrPrefix">PLC地址类型,默认值R</param>
        /// <returns></returns>
        public static List<AlarmStatus> OmronEIPByte2Status(int plcAddrSuffix, List<byte> byteData, char plcAddrPrefix = 'W')
        {
            var listAlarmStatus = new List<AlarmStatus>();
            // byte[]转为二进制字符串表示
            string strResult = "";
            for (int i = 0; i < byteData.Count; i++)
            {
                string strTemp = System.Convert.ToString(byteData[i], 2);
                strTemp = strTemp.PadLeft(8, '0').StrReverse();
                strResult += strTemp;
            }

            for (int i = 0; i < strResult.Length; i++)
            {
                var plcByte = i % 16;
                //如果是16的倍数地址+1
                if (plcByte % 16 == 0 && i != 0)
                {
                    plcAddrSuffix++;
                }
                //将地址和状态添加到结果集
                listAlarmStatus.Add(new AlarmStatus()
                {
                    PLCAdress = $"{plcAddrPrefix}6100[{plcAddrSuffix}].B[{plcByte.ToString()}]",
                    Status = strResult[i] == '1'
                });

                //if (strResult[i] == '1')
                //    Console.WriteLine($"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}:{strResult[i]}");
            }

            return listAlarmStatus;
        }


        /// <summary>
        /// 欧姆龙FINS通讯读取EM数据寄存器是时将报警地址值转成报警List
        /// </summary>
        /// <param name="plcAddrSuffix">PLC地址值，如100</param>
        /// <param name="byteData">PLC读取出来的值</param>
        /// <param name="plcAddrPrefix">PLC地址类型,默认值W</param>
        /// <returns></returns>
        public static List<AlarmStatus> OmronFinsByte2Status(int plcAddrSuffix, byte[] byteData, char plcAddrPrefix = 'D')
        {
            var listAlarmStatus = new List<AlarmStatus>();
            #region 取消
            // byte[]转为二进制字符串表示
            //byte[] revBytes = SWAPbyte(byteData); //字节高低位互换
            //string strResult = "";
            //for (int i = 0; i < revBytes.Length; i++)
            //{
            //    string strTemp = System.Convert.ToString(revBytes[i], 2);
            //    strTemp = strTemp.PadLeft(8, '0').StrReverse();
            //    strResult += strTemp;
            //}

            //for (int i = 0; i < strResult.Length; i++)
            //{
            //    var plcByte = i % 500;
            //    //如果是16的倍数地址+1
            //    if (plcByte % 500 == 0 && i != 0)
            //    {
            //        plcAddrSuffix++;
            //    }
            //    //将地址和状态添加到结果集
            //    listAlarmStatus.Add(new AlarmStatus()
            //    {
            //        PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString()}",
            //        Status = strResult[i] == '1'
            //    });
            //    //if (strResult[i] == '1')
            //    //    Console.WriteLine($"{plcAddrPrefix}{plcAddrSuffix}.{plcByte.ToString("X")}:{strResult[i]}");
            //}

            //将地址和状态添加到结果集
            //for (int i = 0; i < byteData.Length / 2; i++)
            //{
            //    listAlarmStatus.Add(new AlarmStatus()
            //    {
            //        PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix + i}",
            //        Status = ShortLib.GetShortFromByteArray(byteData, (i * 2)) == 1,
            //        //Status = strResult[i] == '1'
            //    });
            //}
            #endregion
            int wordCount = byteData.Length / 2;  // 16位整数数量

            for (int i = 0; i < wordCount; i++)
            {
                int currentAddr = plcAddrSuffix + i;
                int byteOffset = i * 2;

                // 组合字节为16位整数（大端序）
                ushort wordValue = (ushort)(
                    (byteData[byteOffset] << 8) |
                    byteData[byteOffset + 1]
                );

                // 跳过0值（无报警）
                if (wordValue == 0) continue;

                // 计算位地址（从1开始）
                int bitPosition = wordValue;
                string address = $"{plcAddrPrefix}{currentAddr}.{bitPosition}";

                // 添加到报警列表（只添加实际触发的位）
                listAlarmStatus.Add(new AlarmStatus()
                {
                    PLCAdress = address,
                    Status = true // 只有触发的位才会被添加
                });
            }
            return listAlarmStatus;

        }


        /// <summary>
        /// 欧姆龙FINS通讯读取W数据寄存器是时将报警地址值转成报警List
        /// </summary>
        /// <param name="plcAddrSuffix">PLC地址值，如100</param>
        /// <param name="byteData">PLC读取出来的值</param>
        /// <param name="plcAddrPrefix">PLC地址类型,默认值W</param>
        /// <returns></returns>
        //public static List<AlarmStatus> OmronByte2Status(int plcAddrSuffix, byte[] byteData, char plcAddrPrefix = 'W')
        //{
        //    var listAlarmStatus = new List<AlarmStatus>();

        //    var addrCount = byteData.Length / 2;
        //    // byte[]每个地址保存的都是bool值，只取双数index位
        //    for (int i = 0; i < addrCount; i++)
        //    {
        //        //将地址和状态添加到结果集
        //        listAlarmStatus.Add(new AlarmStatus()
        //        {
        //            PLCAdress = $"{plcAddrPrefix}{plcAddrSuffix + i}",
        //            Status = byteData[i * 2 + 1] == 1

        //        });
        //        //if (byteData[i * 2 + 1] == 1)
        //        //    Console.WriteLine($"原始数据 PLC地址:{plcAddrPrefix}{plcAddrSuffix + i} 报警值：{byteData[i * 2 + 1]}");
        //    }

        //    return listAlarmStatus;
        //}




        /// <summary>
        /// 字符串反转
        /// </summary>
        /// <param name="str">需要反转字符串.Reverse()</param>
        /// <returns></returns>
        public static string StrReverse(this string str)
        {
            return new string(str.Reverse().ToArray());
        }


        /// <summary>
        ///byte字节高低位互换
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] SWAPbyte(byte[] data)
        {
            byte[] data2 = new byte[data.Length];
            for (int i = 0; i < data.Length; i += 2)
            {
                data2[i] = data[i + 1];
                data2[i + 1] = data[i];
            }
            return data2;
        }
    }
}

